package com.ccrfid.rmc6.service.device;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.device.CardEntity;
import com.ccrfid.rmc6.entity.device.CardreaderEntity;
import com.ccrfid.rmc6.lbservice3.manager.ClientManager;
import com.ccrfid.rmc6.repository.device.CardRepository;
import com.ccrfid.rmc6.repository.device.CardreaderRepository;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.util.CalcUtil;
import com.ccrfid.rmc6.ws.c5.cardreader.pojo.UploadCardRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.transaction.Transactional;
import javax.ws.rs.core.Response;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Transactional
public class CardreaderServiceImpl implements CardreaderService {
    private static final Logger logger = LoggerFactory.getLogger(CardreaderServiceImpl.class);
    private Map<Long, Long> readCardCache;
    @Autowired
    private CardreaderRepository cardreaderRepository;
    @Autowired
    private CardRepository cardRepository;
    @Autowired
    private ClientManager clientManager;

    @PostConstruct
    public void init() {
        this.readCardCache = new ConcurrentHashMap<>();
    }

    @Override
    public Page<CardreaderEntity> getCardreaderInfoPage(SearchCriteria criteria, Pageable pageable) {
        Page<CardreaderEntity> page = cardreaderRepository.search(criteria, pageable);
        return page;
    }

    @Override
    public CardreaderEntity getCardreaderById(Long readerId) {
        return cardreaderRepository.getById(readerId);
    }

    @Override
    public CardreaderEntity createCardreaderEntity(CardreaderEntity entity) throws AppException {
        if (cardreaderRepository.existsBySn(entity.getSn())) {
            throw new AppException(Response.Status.CONFLICT.getStatusCode(),
                    CustomErrors.sn_conflict.getCode(), CustomErrors.sn_conflict.getReason(), "");
        }
        return cardreaderRepository.save(entity);
    }

    @Override
    public CardreaderEntity updateCardreaderEntity(Long readerId, CardreaderEntity entity) throws AppException {
        if (!cardreaderRepository.existsById(readerId) || !readerId.equals(entity.getId())) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        CardreaderEntity ce = cardreaderRepository.getBySn(entity.getSn());
        if (ce != null && !ce.getId().equals(readerId)) {
            throw new AppException(Response.Status.CONFLICT.getStatusCode(),
                    CustomErrors.sn_conflict.getCode(), CustomErrors.sn_conflict.getReason(), "");
        }
        return cardreaderRepository.save(entity);
    }

    @Override
    public int deleteCardreadersInfo(List<Long> readerIdList) {
        int count = 0;
        for (Long readerId : readerIdList) {
            if (cardreaderRepository.existsById(readerId)) {
                //删除读卡器信息
                cardreaderRepository.deleteById(readerId);
                count++;
            }
        }
        return count;
    }

    @Override
    public void readCard(UploadCardRequest request) {
        Long cardNumber = request.getCardNumber();
        Long timeNow = new Date().getTime();
        if (readCardCache.containsKey(cardNumber)) {
            if (timeNow - readCardCache.get(cardNumber) > 2018) {
                postReadCardMsg(request);
            }
        } else {
            postReadCardMsg(request);
        }
        readCardCache.put(cardNumber, timeNow);
    }

    private void postReadCardMsg(UploadCardRequest request) {
        CardreaderEntity cardreaderEntity = cardreaderRepository.getBySn(request.getCardReaderNumber());
        if (StringUtils.isEmpty(request.getCardReaderNumber()) ||
                (cardreaderEntity != null && cardreaderEntity.getEnabled().equals(1))) {
            CardEntity cardEntity;
            if (cardRepository.existsByCardNumber(request.getCardNumber())) {
                cardEntity = cardRepository.getByCardNumber(request.getCardNumber());
            } else {
                cardEntity = new CardEntity();
                cardEntity.setCardNumber(request.getCardNumber());
                cardEntity.setHexNumber(Long.toHexString(request.getCardNumber()).toUpperCase());
                cardEntity.setSn(request.getCardIcNumber());
                cardEntity.setUid(CalcUtil.getCardUid(request.getCardIcNumber()));
            }
            String[] ipAddrs = request.getIpAddrs().split(",");
            for (String ip : ipAddrs) {
                if (clientManager.postReadCardMsg(ip, cardEntity)) {
                    break;
                }
            }
        } else {
            logger.debug("Cardreader {} not found, or not enabled.", request.getCardReaderNumber());
            String[] ipAddrs = request.getIpAddrs().split(",");
            for (String ip : ipAddrs) {
                if (clientManager.postCardReaderNotFoundMsg(ip, request)) {
                    break;
                }
            }
        }
    }
}
